#ifndef APPLICATION_H
#define APPLICATION_H

#include "Constants.h"
#include "Shader.h"
#include "Mouse.h"
#include "Camera.h"
#include "Light.h"
#include "Object.h"
#include "Model.h"
#include "Material.h"
#include "Helpers.h"

#include <GL/glew.h>
#include <GL/glfw.h>
#include <GL/gl.h>

#include <glm/glm.hpp>

#include <vector>
#include <string>

using std::vector;
using glm::vec2;
using glm::vec3;

class Application
{
public:

	explicit Application();
	~Application();

	void initialize();
    bool running();
    void handleInput();
    void update();
    void render();       

private:

	// Disable copying.
	Application(Application const& rhs);
	Application& operator=(Application const& rhs);

    // Functions.
    void initEntities();
    void initPostprocess();
    void setTextureUniforms();
    void loadShader(const string& shader); 

    template <class T, class U, class V> 
    void SetObjectReference(T& container, U& reference, const string& name);

    // Constants.
    static const GLfloat QUAD_VERTEX_BUFFER[24];

    // Variables.
    bool m_running;

    vector<Object*> m_objects;
    vector<Light> m_lights;
    vector<Shader*> m_shaders;
    vector<Model*> m_models;
    vector<Material*> m_materials;

    Mouse m_mouse;
    Camera m_camera;

    GLuint m_quadVao;
    GLuint m_quadVbo;

    GLuint m_postprocFramebuffer;
    GLuint m_postprocTexture;
    GLuint m_postprocDepthRenderbuffer;    
    GLuint m_postprocTexLocation;

    GLuint m_depthTexture;
    GLuint m_depthTexLocation;

    GLuint m_glowFramebuffer;
    GLuint m_glowTexture;
    GLuint m_glowDepthRenderbuffer;    
    GLuint m_glowTexLocation;

    Shader m_postprocess;

    double m_time;
};

#endif // APPLICATION_H